package com.ybt.ruleengine.expander.router;

import java.util.Properties;

import org.apache.log4j.Logger;

import com.ruleengine.context.IContextProperty;
import com.ruleengine.context.IWorkflowConext;
import com.ruleengine.context.IWorkflowContextConstants;
import com.ruleengine.endpoint.data.IEndpointData;
import com.ruleengine.frame.callback.IRuleEngineCallback;
import com.ruleengine.frame.impl.WorkflowExecuter;
import com.ruleengine.router.exception.RouterException;
import com.ruleengine.router.impl.AbstractRouter;
import com.ybt.context.IYBTContextConstants;
import com.ybt.context.util.ContextUtil;
import com.ybt.pub.ObjectSerializationUtil;
import com.ybt.router.client.MessageClient;
import com.ybt.router.core.message.IMSDMessageConstants;
import com.ybt.router.tcp.routertable.TCPServiceRouter;
import com.ybt.router.tcp.routertable.manager.TCPRouterManager;
import com.ybt.ruleengine.expander.router.util.RuleEngineCallbackPool;

/**
 * 本地路由工作流调用。
 * 本地路由是默认工作流路由器
 * @author AB033862
 * Aug 23, 2012
 */
public class RemoteRouter extends AbstractRouter {
    private static Logger logger = Logger.getLogger(RemoteRouter.class);

    public void route(final String target, final IWorkflowConext context,
            final IEndpointData data) throws RouterException {
        TCPServiceRouter router = TCPRouterManager.getInstance().getRouter(target);
        if(router==null){
            //分布式路由信息中没有该工作流配置
            if(logger.isDebugEnabled()){
                logger.debug("can't find router information in serviceRouter.xml for task ["+target+"]");
            }
            //调用下一个路由器处理
            getRouter().route(target, context, data);
            return;
        }

        if(logger.isDebugEnabled()){
            logger.debug("the router information for task ["+target+"] is "+router);
        }

        try {
            // 拷贝消息头
            Properties p = ContextUtil.getSeriPropertys(context);
            p.setProperty(IMSDMessageConstants.MSD_FROM, context.getWorkflowId());
            p.setProperty(IMSDMessageConstants.MSD_TO, target);
            p.setProperty(IMSDMessageConstants.MSD_DESTINATION,target);

            // 拷贝消息体
            IContextProperty<Object> dataPro = context
            .getContextProperty(IYBTContextConstants.ORIGINAL_DATA);
            byte[] body = dataPro.getValue() == null ? new byte[0]
                                                                : ObjectSerializationUtil.toByte(dataPro.getValue());

            // 执行id
            IContextProperty<String> idPro = context
            .getContextProperty(IWorkflowContextConstants.WORKFLOW_EXECUTE_ID);
            String excuteId = idPro.getValue();

            //初始化回调对象
            IRuleEngineCallback callback =  new IRuleEngineCallback() {
                private IWorkflowConext oriContext = context;
                private String subTarget = target;

                public void onException(IWorkflowConext context,
                        Exception e) {
                    // TODO Auto-generated method stub
                    logger.debug("excute sub workflow ["
                            + oriContext.getWorkflowId() + "-->"
                            + subTarget + "] on exception");
                    // 设置异常
                    oriContext.setExceptionCause(e);

                    WorkflowExecuter.getInstance().executeCallBack(
                            oriContext, data);
                }

                public void onComplete(IWorkflowConext context,
                        IEndpointData data1) {
                    // TODO Auto-generated method stub
                    logger.debug("excute sub workflow ["
                            + oriContext.getWorkflowId() + "-->"
                            + subTarget + "] on complete");
                    // 合并public属性
                    oriContext.combination(context);

                    // 合并业务数据
                    if(data1 != null){
                        data.setOutData(data1.getOutData());
                    }

                    // 执行回调
                    WorkflowExecuter.getInstance().executeCallBack(
                            oriContext, data);
                }

            };

            //缓存回调对象
            RuleEngineCallbackPool.getInstance().putRuleEngineCallback(excuteId, callback);

            // 发送消息
            MessageClient.getInstance().sendOneWay(body, p);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new RouterException("route workflow task [" + target
                    + "] error", e);
        }
    }

}
